commit 756aba6844b16a86053ae33537b65fdc9e787405
parent f05bc63288d5d15c3f055e573314a78f02fdb096
Author: Andrea Feletto <andrea@andreafeletto.com>
Date: Sun, 30 Jan 2022 20:17:32 +0100
use udev for battery
Diffstat:
M | src/event.zig | | | 33 | ++++----------------------------- |
M | src/modules.zig | | | 127 | ++++++++++++++++++++++++++++++++++++++++++------------------------------------- |
2 files changed, 71 insertions(+), 89 deletions(-)
diff --git a/src/event.zig b/src/event.zig
@@ -6,13 +6,12 @@ const ArrayList = std.ArrayList;
const wl = @import("wayland").client.wl;
const udev = @import("udev");
-const c = @import("c.zig");
const render = @import("render.zig");
const State = @import("main.zig").State;
pub const Loop = struct {
state: *State,
- fds: [5]os.pollfd,
+ fds: [4]os.pollfd,
monitor: *udev.Monitor,
pub fn init(state: *State) !Loop {
@@ -35,13 +34,11 @@ pub const Loop = struct {
};
_ = os.linux.timerfd_settime(@intCast(i32, tfd), 0, &interval, null);
- // inotify
- const ifd = os.linux.inotify_init1(os.linux.IN.CLOEXEC);
-
// udev
const context = try udev.Udev.new();
const monitor = try udev.Monitor.newFromNetlink(context, "udev");
try monitor.filterAddMatchSubsystemDevType("backlight", null);
+ try monitor.filterAddMatchSubsystemDevType("power_supply", null);
try monitor.enableReceiving();
const ufd = try monitor.getFd();
@@ -64,11 +61,6 @@ pub const Loop = struct {
.revents = 0,
},
.{
- .fd = @intCast(os.fd_t, ifd),
- .events = os.POLL.IN,
- .revents = 0,
- },
- .{
.fd = @intCast(os.fd_t, ufd),
.events = os.POLL.IN,
.revents = 0,
@@ -80,7 +72,6 @@ pub const Loop = struct {
pub fn run(self: *Loop) !void {
const display = self.state.wayland.display;
- const tfd = self.fds[2].fd;
while (true) {
while (true) {
@@ -114,6 +105,7 @@ pub const Loop = struct {
// timer
if (self.fds[2].revents & os.POLL.IN != 0) {
+ const tfd = self.fds[2].fd;
var expirations = mem.zeroes([8]u8);
_ = try os.read(tfd, &expirations);
@@ -128,25 +120,8 @@ pub const Loop = struct {
}
}
- // inotify
- if (self.fds[3].revents & os.POLL.IN != 0) {
- const ifd = self.fds[3].fd;
- var event = mem.zeroes(os.linux.inotify_event);
- _ = try os.read(ifd, mem.asBytes(&event));
-
- for (self.state.wayland.outputs.items) |output| {
- if (output.surface) |surface| {
- if (surface.configured) {
- render.renderModules(surface) catch continue;
- surface.modulesSurface.commit();
- surface.backgroundSurface.commit();
- }
- }
- }
- }
-
// udev
- if (self.fds[4].revents & os.POLL.IN != 0) {
+ if (self.fds[3].revents & os.POLL.IN != 0) {
_ = try self.monitor.receiveDevice();
for (self.state.wayland.outputs.items) |output| {
diff --git a/src/modules.zig b/src/modules.zig
@@ -31,36 +31,29 @@ pub const Module = struct {
pub const Battery = struct {
state: *State,
- path: []const u8,
- watch: i32,
+ context: *udev.Udev,
+ devices: DeviceList,
- pub const Data = struct {
- value: u8,
- icon: []const u8,
+ const Device = struct {
+ name: []const u8,
+ voltage: u64,
+ charge: u64,
+ charge_full: u64,
+ status: []const u8,
};
+ const DeviceList = std.ArrayList(Device);
pub fn init(state: *State) !Battery {
- const path = try fs.path.join(
- state.allocator,
- &.{ "/sys/class/power_supply", state.config.batteryDev },
- );
-
- const uevent_path = try fs.path.joinZ(
- state.allocator,
- &.{ path, "uevent" },
- );
- defer state.allocator.free(uevent_path);
-
- const watch = os.linux.inotify_add_watch(
- state.loop.fds[3].fd,
- uevent_path,
- os.linux.IN.ACCESS,
- );
+ const context = try udev.Udev.new();
+
+ var devices = DeviceList.init(state.allocator);
+ try updateDevices(state.allocator, context, &devices);
+ if (devices.items.len == 0) return error.NoDevicesFound;
return Battery{
.state = state,
- .path = path,
- .watch = @intCast(i32, watch),
+ .context= context,
+ .devices = devices,
};
}
@@ -71,59 +64,73 @@ pub const Battery = struct {
pub fn print(self_opaque: *anyopaque, writer: StringWriter) !void {
const self = Module.cast(Battery)(self_opaque);
- const data = try self.readData();
- try fmt.format(writer, "{s} {d}%", .{ data.icon, data.value });
- }
-
- fn readData(self: *const Battery) !Data {
- const voltage = try self.readInt("voltage_now");
- const charge = try self.readInt("charge_now");
- const charge_full = try self.readInt("charge_full");
-
- const energy = @as(u64, charge) * @as(u64, voltage) / 1000000;
- const energy_full = @as(u64, charge_full) * @as(u64, voltage) / 1000000;
+ try updateDevices(self.state.allocator, self.context, &self.devices);
+ const device = self.devices.items[0];
+ const energy = device.charge * device.voltage / 1000000;
+ const energy_full = device.charge_full * device.voltage / 1000000;
var capacity = @intToFloat(f64, energy) * 100.0;
capacity /= @intToFloat(f64, energy_full);
- const status = try self.readValue("status");
-
var icon: []const u8 = "❓";
- if (mem.eql(u8, status, "Discharging")) {
+ if (mem.eql(u8, device.status, "Discharging")) {
icon = "🔋";
- } else if (mem.eql(u8, status, "Charging")) {
+ } else if (mem.eql(u8, device.status, "Charging")) {
icon = "🔌";
- } else if (mem.eql(u8, status, "Full")) {
+ } else if (mem.eql(u8, device.status, "Full")) {
icon = "⚡";
}
- return Data{
- .value = @floatToInt(u8, @round(capacity)),
- .icon = icon,
- };
+ const value = @floatToInt(u8, @round(capacity));
+ try fmt.format(writer, "{s} {d}%", .{ icon, value });
}
- fn readInt(self: *const Battery, filename: []const u8) !u32 {
- const value = try self.readValue(filename);
- defer self.state.allocator.free(value);
+ fn updateDevices(
+ allocator: mem.Allocator,
+ context: *udev.Udev,
+ devices: *DeviceList,
+ ) !void {
+ const enumerate = try udev.Enumerate.new(context);
+ try enumerate.addMatchSubsystem("power_supply");
+ try enumerate.addMatchSysattr("type", "Battery");
+ try enumerate.scanDevices();
+ const entries = enumerate.getListEntry();
- return fmt.parseInt(u32, value, 10);
+ var maybe_entry = entries;
+ while (maybe_entry) |entry| {
+ const path = entry.getName();
+ const device = try udev.Device.newFromSyspath(context, path);
+ try updateOrAppend(allocator, devices, device);
+ maybe_entry = entry.getNext();
+ }
}
- fn readValue(self: *const Battery, filename: []const u8) ![]u8 {
- const state = self.state;
-
- const path = try fs.path.join(
- state.allocator,
- &.{ self.path, filename },
- );
- defer state.allocator.free(path);
-
- const file = try fs.openFileAbsolute(path, .{});
- defer file.close();
+ fn updateOrAppend(
+ allocator: mem.Allocator,
+ devices: *DeviceList,
+ dev: *udev.Device,
+ ) !void {
+ const voltage = try dev.getSysattrValue("voltage_now");
+ const charge = try dev.getSysattrValue("charge_now");
+ const charge_full = try dev.getSysattrValue("charge_full");
+ const status = try dev.getSysattrValue("status");
+ const name = try dev.getSysname();
- var str = try file.readToEndAlloc(state.allocator, 128);
- return state.allocator.resize(str, str.len - 1).?;
+ const device = blk: {
+ for (devices.items) |*device| {
+ if (mem.eql(u8, device.name, name)) {
+ break :blk device;
+ }
+ } else {
+ const device = try devices.addOne();
+ device.name = try allocator.dupe(u8, name);
+ break :blk device;
+ }
+ };
+ device.voltage = try fmt.parseInt(u64, voltage, 10);
+ device.charge = try fmt.parseInt(u64, charge, 10);
+ device.charge_full = try fmt.parseInt(u64, charge_full, 10);
+ device.status = try allocator.dupe(u8, status);
}
};