/* * power - zavai power event handling * * Copyright (C) 2009 Enrico Zini * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ using GLib; namespace zavai { namespace power { public class Power : Service { public enum State { UNKNOWN, CHARGING, DISCHARGING, FULLY_CHARGED, } protected string battery_device; protected uint timeout; public signal void changed(); public State state; public int percentage; public Power() { battery_device = "/sys/class/power_supply/battery/"; if (Posix.access(battery_device, Posix.R_OK) != 0) battery_device = null; timeout = 0; state = State.UNKNOWN; percentage = 0; } /// Activate the service protected override void start() { if (started) return; uint poll_time; if (uevent.uevent != null) { zavai.log.info("We have uevent: poll rarely"); uevent.uevent.event += on_uevent; uevent.uevent.request("zavai.power"); // If we can get plug/unplug notifications, it's ok to just poll // every 5 minutes poll_time = 300 * 1000; } else { if (battery_device == null) { zavai.log.warning("No battery device found that I know how to read: try building with devkit-power"); poll_time = 0; } else { zavai.log.info("Polling battery device only"); // Else poll every 30 seconds to be somehow reactive to plug/unplug // events poll_time = 30 * 1000; } } poll(); // Poll battery every minute if (poll_time != 0) timeout = Timeout.add(poll_time, on_timeout); base.start(); } /// Deactivate the service protected override void stop() { if (!started) return; // Stop polling if (timeout != 0) Source.remove(timeout); if (uevent.uevent != null) { uevent.uevent.release("zavai.power"); uevent.uevent.event -= on_uevent; } base.stop(); } protected void poll() { if (battery_device == null) return; char buf[200]; State new_state = State.UNKNOWN; int new_percentage = 0; FileStream state_fd = FileStream.open(battery_device + "/status", "r"); string val = state_fd.gets(buf); if (val == "Charging") new_state = State.CHARGING; else if (val == "Discharging") new_state = State.DISCHARGING; else if (val == "Not charging") new_state = State.FULLY_CHARGED; FileStream cap_fd = FileStream.open(battery_device + "/capacity", "r"); val = cap_fd.gets(buf); new_percentage = val.to_int(); if (new_state != state || new_percentage != percentage) { state = new_state; percentage = new_percentage; changed(); } } protected bool on_timeout() { poll(); return true; } protected void on_uevent() { /* if (uevent.uevent.event_data.buffer.has_prefix("change@/class/power_supply/ac")) { changed(); } else */ if (uevent.uevent.event_data.buffer.has_prefix("change@/class/power_supply/battery")) { State new_state = State.UNKNOWN; int new_percentage = 0; Omhacks.UEvent.parse(ref uevent.uevent.event_data); for (int i = 0; uevent.uevent.event_data.envp[i] != null; ++i) { if (uevent.uevent.event_data.envp[i].has_prefix("POWER_SUPPLY_STATUS=")) { var val = uevent.uevent.event_data.envp[i].offset(20); if (val == "Charging") new_state = State.CHARGING; else if (val == "Discharging") new_state = State.DISCHARGING; else if (val == "Not charging") new_state = State.FULLY_CHARGED; else zavai.log.warning("Unknown state: " + uevent.uevent.event_data.envp[i]); } else if (uevent.uevent.event_data.envp[i].has_prefix("POWER_SUPPLY_CAPACITY=")) { new_percentage = uevent.uevent.event_data.envp[i].offset(22).to_int(); } } if (new_state != state || new_percentage != percentage) { state = new_state; percentage = new_percentage; changed(); } } } } public Power power; public void init() { power = new Power(); } } }