aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys-mobilephone/fsousaged/Manifest5
-rw-r--r--sys-mobilephone/fsousaged/files/controller-plugin.vala769
-rw-r--r--sys-mobilephone/fsousaged/files/lowlevel_kernel26-plugin.vala68
-rw-r--r--sys-mobilephone/fsousaged/files/lowlevel_openmoko-plugin.vala130
-rw-r--r--sys-mobilephone/fsousaged/fsousaged-0.9.1.0.ebuild45
5 files changed, 1017 insertions, 0 deletions
diff --git a/sys-mobilephone/fsousaged/Manifest b/sys-mobilephone/fsousaged/Manifest
index 6ef9eee..45483f0 100644
--- a/sys-mobilephone/fsousaged/Manifest
+++ b/sys-mobilephone/fsousaged/Manifest
@@ -1,3 +1,8 @@
+AUX controller-plugin.vala 25009 RMD160 c39962369724c4495a4bdfd77260e2babb612182 SHA1 daba7e911a1dca7c6ca2ec79e26f2d38718ab9f7 SHA256 88e4add559409bc95ce33c9d956b4e2526c9546ff93074ba968270024e708c90
AUX fsousaged_main.patch 450 RMD160 21c2bb26374ff1ac9243d57ac38cd98805dcee27 SHA1 c7c5b15e283f3b5c7f99ed418306182d4b7ab6cb SHA256 522b2638c9a547fdad23dfb92d6227447786a62c4c402ed60e8008770642b32a
+AUX lowlevel_kernel26-plugin.vala 2048 RMD160 7788ad6d53adde7a44b8678b2563334cebad988c SHA1 2f5be77178bc679158c66de9b7a1f69d82ecc326 SHA256 4c4f088c5e512c7fff0ed78f77c61b4525ed9074df259b0c7c0ff84d83162918
+AUX lowlevel_openmoko-plugin.vala 5023 RMD160 ede1b1ccdb3682b1d313f4a64aba59980390fb17 SHA1 311bc5bce80af622f40a70605ad53dc24884dc97 SHA256 cb8cdf0d9cb5b93c9926ad55c253ee8755e87928dc8355acb835ffeac4cc5c00
DIST fsousaged-0.9.0.tar.gz 19121 RMD160 6bb47885af8ee7a9efc272795d7ea67622a18818 SHA1 f69395d25fb5e52e928a14068b2a7deda61d33ea SHA256 a7d07e7022806bf525feff56bd99462bdbff48a2019938ade50915cd9ac3166b
+DIST fsousaged-0.9.1.0.tar.bz2 249038 RMD160 d6107e2925b717b74d0c62947eb48a748e475dcd SHA1 7656172f4cbba2e15a4e1d3cfe7067b7da0a9ce8 SHA256 2a456677f8c6487f14e2f4346ceb289387a2afe1204e37201369cf6358779d7b
EBUILD fsousaged-0.9.0.ebuild 1125 RMD160 72333aa53e002afb65ffc992f587e3c447ad6fec SHA1 dd8046419738a4ad19253365533008dfd57655ab SHA256 6d9465fcbc25b491345095f47de2b2a88dc2153e2537444330dd539789b03936
+EBUILD fsousaged-0.9.1.0.ebuild 1348 RMD160 83912073652866a555c4b671ee0c8ff7815ac245 SHA1 d62c356af79746f05f58fa44c2cbb025fd685ea2 SHA256 0b45f0726fb18830d85b04bfaa6550e488315387a41b317d47a0aca25631e0f5
diff --git a/sys-mobilephone/fsousaged/files/controller-plugin.vala b/sys-mobilephone/fsousaged/files/controller-plugin.vala
new file mode 100644
index 0000000..eb14bdc
--- /dev/null
+++ b/sys-mobilephone/fsousaged/files/controller-plugin.vala
@@ -0,0 +1,769 @@
+/*
+ * Generic Resource Controller
+ *
+ * Written by Michael 'Mickey' Lauer <mlauer@vanille-media.de>
+ * All Rights Reserved
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+using GLib;
+using Gee;
+
+internal const string RESOURCE_INTERFACE = "org.freesmartphone.Resource";
+internal const string CONFIG_SECTION = "fsousage";
+internal const string DEFAULT_LOWLEVEL_MODULE = "kernel26";
+
+internal const string FSO_IDLENOTIFIER_BUS = "org.freesmartphone.odeviced";
+internal const string FSO_IDLENOTIFIER_PATH = "/org/freesmartphone/Device/IdleNotifier/0";
+internal const string FSO_IDLENOTIFIER_IFACE = "org.freesmartphone.Device.IdleNotifier";
+
+namespace Usage
+{
+/**
+ * Enum for resource status
+ **/
+public enum ResourceStatus
+{
+ UNKNOWN,
+ ENABLING,
+ ENABLED,
+ SUSPENDING,
+ SUSPENDED,
+ RESUMING,
+ DISABLING,
+ DISABLED
+}
+
+/**
+ * Helper class encapsulating a registered resource
+ **/
+public class Resource : Object
+{
+ public string name { get; set; }
+ public DBus.BusName busname { get; set; }
+ public DBus.ObjectPath objectpath { get; set; }
+ public ResourceStatus status { get; set; }
+ public FreeSmartphone.UsageResourcePolicy policy { get; set; }
+ public ArrayList<string> users { get; set; }
+
+ private FreeSmartphone.Resource proxy;
+
+ // called before deserializing, init all non-value types here
+ construct
+ {
+ this.users = new ArrayList<string>( str_equal );
+ }
+
+ public Resource( string name, DBus.BusName busname, DBus.ObjectPath objectpath )
+ {
+ this.name = name;
+ this.busname = busname;
+ this.objectpath = objectpath;
+ this.status = ResourceStatus.UNKNOWN;
+ this.policy = FreeSmartphone.UsageResourcePolicy.AUTO;
+
+ proxy = dbusconn.get_object( busname, objectpath, RESOURCE_INTERFACE ) as FreeSmartphone.Resource;
+ // workaround until vala 0.7.4
+ proxy.ref();
+
+ //message( "Resource %s served by %s @ %s created", name, busname, objectpath );
+ }
+
+ ~Resource()
+ {
+ //message( "Resource %s served by %s @ %s destroyed", name, busname, objectpath );
+ }
+
+ private void updateStatus()
+ {
+ var info = new HashTable<string,Value?>( str_hash, str_equal );
+ var p = Value( typeof(int) );
+ p.set_int( policy );
+ info.insert( "policy", p );
+ var u = Value( typeof(int) );
+ u.set_int( users.size );
+ info.insert( "refcount", u );
+ instance.resource_changed( name, isEnabled(), info ); // DBUS SIGNAL
+ }
+
+ public bool isEnabled()
+ {
+ return ( status == ResourceStatus.ENABLED );
+ }
+
+ public bool hasUser( string user )
+ {
+ return ( user in users );
+ }
+
+ public void setPolicy( FreeSmartphone.UsageResourcePolicy policy )
+ {
+ if ( policy == this.policy )
+ return;
+ else
+ ( this.policy = policy );
+
+ switch ( policy )
+ {
+ case FreeSmartphone.UsageResourcePolicy.DISABLED:
+ disable();
+ break;
+ case FreeSmartphone.UsageResourcePolicy.ENABLED:
+ enable();
+ break;
+ case FreeSmartphone.UsageResourcePolicy.AUTO:
+ if ( users.size > 0 )
+ enable();
+ else
+ disable();
+ break;
+ default:
+ assert_not_reached();
+ }
+
+ updateStatus();
+ }
+
+ public void addUser( string user ) throws FreeSmartphone.UsageError
+ {
+ if ( user in users )
+ throw new FreeSmartphone.UsageError.USER_EXISTS( "Resource %s already requested by user %s".printf( name, user ) );
+
+ if ( policy == FreeSmartphone.UsageResourcePolicy.DISABLED )
+ throw new FreeSmartphone.UsageError.POLICY_DISABLED( "Resource %s cannot be requested by %s per policy".printf( name, user ) );
+
+ users.insert( 0, user );
+
+ if ( policy == FreeSmartphone.UsageResourcePolicy.AUTO && users.size == 1 )
+ enable();
+
+ updateStatus();
+ }
+
+ public void delUser( string user ) throws FreeSmartphone.UsageError
+ {
+ if ( !(user in users) )
+ throw new FreeSmartphone.UsageError.USER_UNKNOWN( "Resource %s never been requested by user %s".printf( name, user ) );
+
+ users.remove( user );
+
+ if ( policy == FreeSmartphone.UsageResourcePolicy.AUTO && users.size == 0 )
+ disable();
+
+ updateStatus();
+ }
+
+ public void syncUsers()
+ {
+ dynamic DBus.Object busobj = dbusconn.get_object( DBus.DBUS_SERVICE_DBUS, DBus.DBUS_PATH_DBUS, DBus.DBUS_INTERFACE_DBUS );
+ string[] busnames = busobj.ListNames();
+
+ var usersToRemove = new ArrayList<string>();
+
+ foreach ( var userbusname in users )
+ {
+ var found = false;
+ foreach ( var busname in busnames )
+ {
+ if ( userbusname == busname )
+ found = true;
+ break;
+ }
+ if ( !found )
+ usersToRemove.add( userbusname );
+ }
+ foreach ( var userbusname in usersToRemove )
+ {
+ instance.logger.warning( "Resource %s user %s has vanished.".printf( name, userbusname ) );
+ delUser( userbusname );
+ }
+ }
+
+ public string[] allUsers()
+ {
+ string[] res = {};
+ foreach ( var user in users )
+ res += user;
+ return res;
+ }
+
+ public bool isPresent()
+ {
+ dynamic DBus.Object peer = dbusconn.get_object( busname, objectpath, DBus.DBUS_INTERFACE_PEER );
+ try
+ {
+ peer.Ping();
+ return true;
+ }
+ catch ( DBus.Error e )
+ {
+ instance.logger.warning( "Resource %s incommunicado: %s".printf( name, e.message ) );
+ return false;
+ }
+ }
+
+ public void enable() throws FreeSmartphone.ResourceError, DBus.Error
+ {
+ try
+ {
+ proxy.enable();
+ status = ResourceStatus.ENABLED;
+ updateStatus();
+ }
+ catch ( DBus.Error e )
+ {
+ instance.logger.error( "Resource %s can't be enabled: %s. Trying to disable instead".printf( name, e.message ) );
+ proxy.disable();
+ throw e;
+ }
+ }
+
+ public void disable() throws FreeSmartphone.ResourceError, DBus.Error
+ {
+ try
+ {
+ proxy.disable();
+ status = ResourceStatus.DISABLED;
+ }
+ catch ( DBus.Error e )
+ {
+ instance.logger.error( "Resource %s can't be disabled: %s. Setting status to UNKNOWN".printf( name, e.message ) );
+ status = ResourceStatus.UNKNOWN;
+ throw e;
+ }
+ }
+
+ public void suspend() throws FreeSmartphone.ResourceError, DBus.Error
+ {
+ if ( status == ResourceStatus.ENABLED )
+ {
+ try
+ {
+ proxy.suspend();
+ status = ResourceStatus.SUSPENDED;
+ }
+ catch ( DBus.Error e )
+ {
+ instance.logger.error( "Resource %s can't be suspended: %s. Trying to disable instead".printf( name, e.message ) );
+ proxy.disable();
+ throw e;
+ }
+ }
+ else
+ {
+ instance.logger.debug( "Resource %s not enabled: not suspending".printf( name ) );
+ }
+ }
+
+ public void resume() throws FreeSmartphone.ResourceError, DBus.Error
+ {
+ if ( status == ResourceStatus.SUSPENDED )
+ {
+ try
+ {
+ proxy.resume();
+ status = ResourceStatus.ENABLED;
+ }
+ catch ( DBus.Error e )
+ {
+ instance.logger.error( "Resource %s can't be resumed: %s. Trying to disable instead".printf( name, e.message ) );
+ proxy.disable();
+ throw e;
+ }
+ }
+ else
+ {
+ instance.logger.debug( "Resource %s not suspended: not resuming".printf( name ) );
+ }
+ }
+}
+
+/**
+ * Serialized state class
+ *
+ * All properties here will be saved on forced shutdown
+ **/
+public class PersistentData : Object
+{
+ public HashMap<string,Resource> resources { get; set; }
+
+ construct
+ {
+ resources = new HashMap<string,Resource>( str_hash, str_equal, str_equal );
+ }
+}
+
+/**
+ * Controller class implementing org.freesmartphone.Usage API
+ *
+ * Note: Unfortunately we can't just use libfso-glib (FreeSmartphone.Usage interface)
+ * here, since we need access to the dbus sender name (which modifies the interface signature).
+ **/
+[DBus (name = "org.freesmartphone.Usage")]
+public class Controller : FsoFramework.AbstractObject
+{
+ private FsoFramework.Subsystem subsystem;
+
+ private FsoUsage.LowLevel lowlevel;
+ private bool do_not_suspend;
+
+ private PersistentData data;
+ private weak HashMap<string,Resource> resources;
+
+ dynamic DBus.Object dbus;
+ dynamic DBus.Object idlenotifier;
+
+ public Controller( FsoFramework.Subsystem subsystem )
+ {
+ this.subsystem = subsystem;
+
+ this.subsystem.registerServiceName( FsoFramework.Usage.ServiceDBusName );
+ this.subsystem.registerServiceObject( FsoFramework.Usage.ServiceDBusName,
+ FsoFramework.Usage.ServicePathPrefix, this );
+
+ // should we really suspend?
+ do_not_suspend = config.boolValue( CONFIG_SECTION, "do_not_suspend", false );
+
+ // start listening for name owner changes
+ dbusconn = ( (FsoFramework.DBusSubsystem)subsystem ).dbusConnection();
+ dbus = dbusconn.get_object( DBus.DBUS_SERVICE_DBUS, DBus.DBUS_PATH_DBUS, DBus.DBUS_INTERFACE_DBUS );
+ dbus.NameOwnerChanged += onNameOwnerChanged;
+
+ // get handle to IdleNotifier
+ idlenotifier = dbusconn.get_object( FSO_IDLENOTIFIER_BUS, FSO_IDLENOTIFIER_PATH, FSO_IDLENOTIFIER_IFACE );
+
+ // delayed init
+ Idle.add( onIdleForInit );
+ }
+
+ public override string repr()
+ {
+ return "<%s>".printf( FsoFramework.Usage.ServicePathPrefix );
+ }
+
+#if PERSISTENCE
+ private void syncResourcesAndUsers()
+ {
+ // for ever resource, we check whether it's still present, and if so,
+ // whether any of the consumers might have disappeared meanwhile
+ var resourcesToRemove = new Gee.HashSet<Resource>();
+
+ foreach ( var r in resources.get_values() )
+ {
+ if ( !r.isPresent() )
+ {
+ resourcesToRemove.add( r );
+ }
+ }
+ foreach ( var r in resourcesToRemove )
+ {
+ resources.remove( r.name );
+ this.resource_available( r.name, false ); // DBUS SIGNAL
+ }
+
+ foreach ( var r in resources.get_values() )
+ {
+ r.syncUsers();
+ }
+ }
+#endif
+
+ private bool onIdleForInit()
+ {
+ // check preferred low level suspend/resume plugin and instanciate
+ var lowleveltype = config.stringValue( CONFIG_SECTION, "lowlevel_type", DEFAULT_LOWLEVEL_MODULE );
+ string typename = "none";
+
+ switch ( lowleveltype )
+ {
+ case "kernel26":
+ typename = "LowLevelKernel26";
+ break;
+ case "openmoko":
+ typename = "LowLevelOpenmoko";
+ break;
+ default:
+ warning( "Invalid lowlevel_type '%s'; suspend/resume will NOT be available!".printf( lowleveltype ) );
+ return false; // don't call me again
+ }
+
+ if ( lowleveltype != "none" )
+ {
+ var lowlevelclass = Type.from_name( typename );
+ if ( lowlevelclass == Type.INVALID )
+ {
+ logger.warning( "Can't find plugin for lowlevel_type = '%s'".printf( lowleveltype ) );
+ return false; // don't call me again
+ }
+
+ lowlevel = Object.new( lowlevelclass ) as FsoUsage.LowLevel;
+ logger.info( "Ready. Using lowlevel plugin '%s' to handle suspend/resume".printf( lowleveltype ) );
+ }
+#if PERSISTENCE
+ // check whether we have crash data
+ if ( loadPersistentData() )
+ {
+ resources = data.resources;
+ syncResourcesAndUsers();
+ }
+ else
+#endif
+ {
+ data = new PersistentData();
+ resources = data.resources;
+ }
+
+ return false; // don't call me again
+ }
+
+ private void onResourceAppearing( Resource r )
+ {
+ logger.debug( "Resource %s served by %s @ %s has just been registered".printf( r.name, r.busname, r.objectpath ) );
+ this.resource_available( r.name, true ); // DBUS SIGNAL
+
+ // initial status is disabled
+ try
+ {
+ r.disable();
+ }
+ catch ( FreeSmartphone.ResourceError e )
+ {
+ logger.warning( "Error while trying to (initially) disable resource %s: %s".printf( r.name, e.message ) );
+ }
+ catch ( DBus.Error e )
+ {
+ logger.warning( "Error while trying to (initially) disable resource %s: %s".printf( r.name, e.message ) );
+ }
+ }
+
+ private void onResourceVanishing( Resource r )
+ {
+ logger.debug( "Resource %s served by %s @ %s has just been unregistered".printf( r.name, r.busname, r.objectpath ) );
+ this.resource_available( r.name, false ); // DBUS SIGNAL
+
+ try
+ {
+ r.disable();
+ }
+ catch ( FreeSmartphone.ResourceError e )
+ {
+ logger.warning( "Error while trying to (initially) disable resource %s: %s".printf( r.name, e.message ) );
+ }
+ catch ( DBus.Error e )
+ {
+ logger.warning( "Error while trying to (finally) disable resource %s: %s".printf( r.name, e.message ) );
+ }
+ }
+
+ private void onNameOwnerChanged( dynamic DBus.Object obj, string name, string oldowner, string newowner )
+ {
+ //message( "name owner changed: %s (%s => %s)", name, oldowner, newowner );
+ // we're only interested in services disappearing
+ if ( newowner != "" )
+ return;
+
+ logger.debug( "%s disappeared. checking whether resources are affected...".printf( name ) );
+
+ //FIXME: Consider keeping the known busnames in a map as well, so we don't have to iterate through all values
+
+ var resourcesToRemove = new Gee.HashSet<Resource>();
+
+ foreach ( var r in resources.get_values() )
+ {
+ // first, check whether the resource provider might have vanished
+ if ( r.busname == name )
+ {
+ onResourceVanishing( r );
+ resourcesToRemove.add( r );
+ }
+ // second, check whether it was one of the users
+ else
+ {
+ if ( r.hasUser( name ) )
+ {
+ r.delUser( name );
+ }
+ }
+ }
+ foreach ( var r in resourcesToRemove )
+ {
+ resources.remove( r.name );
+ }
+ }
+
+ private bool onIdleForSuspend()
+ {
+ suspendAllResources();
+ logger.debug( ">>>>>>> KERNEL SUSPEND" );
+ if ( !do_not_suspend )
+ lowlevel.suspend();
+ else
+ Posix.sleep( 5 );
+ logger.debug( "<<<<<<< KERNEL RESUME" );
+ FsoUsage.ResumeReason reason = lowlevel.resume();
+ logger.info( "Resume reason seems to be %s".printf( FsoFramework.StringHandling.enumToString( typeof( FsoUsage.ResumeReason ), reason) ) );
+ resumeAllResources();
+ this.system_action( FreeSmartphone.UsageSystemAction.RESUME ); // DBUS SIGNAL
+
+ var idlestate = lowlevel.isUserInitiated( reason ) ? "busy" : "idle";
+ try
+ {
+ idlenotifier.SetState( idlestate );
+ }
+ catch ( DBus.Error e )
+ {
+ logger.error( "DBus Error while talking to IdleNotifier: %s".printf( e.message ) );
+ }
+ return false; // MainLoop: Don't call again
+ }
+
+ private Resource getResource( string name ) throws FreeSmartphone.UsageError
+ {
+ Resource r = resources[name];
+ if ( r == null )
+ throw new FreeSmartphone.UsageError.RESOURCE_UNKNOWN( "Resource %s had never been registered".printf( name ) );
+
+ logger.debug( "current users for %s = %s".printf( r.name, FsoFramework.StringHandling.stringListToString( r.allUsers() ) ) );
+
+ return r;
+ }
+
+ private void disableAllResources()
+ {
+ foreach ( var r in resources.get_values() )
+ {
+ try
+ {
+ r.disable();
+ }
+ catch ( FreeSmartphone.ResourceError e )
+ {
+ logger.warning( "Error while trying to suspend resource %s: %s".printf( r.name, e.message ) );
+ }
+ catch ( DBus.Error e )
+ {
+ logger.warning( "Error while trying to disable resource %s: %s".printf( r.name, e.message ) );
+ }
+ }
+ }
+
+ private void suspendAllResources()
+ {
+ foreach ( var r in resources.get_values() )
+ {
+ try
+ {
+ r.suspend();
+ }
+ catch ( FreeSmartphone.ResourceError e )
+ {
+ logger.warning( "Error while trying to suspend resource %s: %s".printf( r.name, e.message ) );
+ }
+ catch ( DBus.Error e )
+ {
+ logger.warning( "Error while trying to suspend resource %s: %s".printf( r.name, e.message ) );
+ }
+ }
+ }
+
+ private void resumeAllResources()
+ {
+ foreach ( var r in resources.get_values() )
+ {
+ try
+ {
+ r.resume();
+ }
+ catch ( FreeSmartphone.ResourceError e )
+ {
+ logger.warning( "Error while trying to suspend resource %s: %s".printf( r.name, e.message ) );
+ }
+ catch ( DBus.Error e )
+ {
+ logger.warning( "Error while trying to resume resource %s: %s".printf( r.name, e.message ) );
+ }
+ }
+ }
+
+#if PERSISTENCE
+ // not public, since we don't want to expose it via dbus
+ internal void savePersistentData()
+ {
+ logger.info( "Saving resource status to file..." );
+ var file = File.new_for_path( "/tmp/serialize.output" );
+ var stream = file.replace( null, false, FileCreateFlags.NONE, null );
+ Persistence.JsonTypeSerializer.instance().ignoreUnknown = true;
+ var serializer = new Persistence.JsonSerializer( stream );
+ serializer.serialize_object( data );
+ }
+
+ internal bool loadPersistentData()
+ {
+ var file = File.new_for_path( "/tmp/serialize.output" );
+ if ( !file.query_exists( null ) )
+ {
+ return false;
+ }
+ var stream = file.read( null );
+ Persistence.JsonTypeSerializer.instance().ignoreUnknown = true;
+ var deserializer = new Persistence.JsonDeserializer<PersistentData>( stream );
+ data = deserializer.deserialize_object() as PersistentData;
+ return true;
+ }
+#endif
+
+ //
+ // DBUS API (for providers)
+ //
+ public void register_resource( DBus.BusName sender, string name, DBus.ObjectPath path ) throws FreeSmartphone.UsageError, DBus.Error
+ {
+ message( "register_resource called with parameters: %s %s %s", sender, name, path );
+ if ( name in resources.get_keys() )
+ throw new FreeSmartphone.UsageError.RESOURCE_EXISTS( "Resource %s already registered".printf( name ) );
+
+ var r = new Resource( name, sender, path );
+ resources[name] = r;
+
+ onResourceAppearing( r );
+ }
+
+ public void unregister_resource( DBus.BusName sender, string name ) throws FreeSmartphone.UsageError, DBus.Error
+ {
+ var r = getResource( name );
+
+ if ( r.busname != sender )
+ throw new FreeSmartphone.UsageError.RESOURCE_UNKNOWN( "Resource %s not yours".printf( name ) );
+
+ onResourceVanishing( r );
+
+ resources.remove( name );
+ }
+
+ //
+ // DBUS API (for consumers)
+ //
+ //public FreeSmartphone.UsageResourcePolicy get_resource_policy( string name ) throws FreeSmartphone.UsageError, FreeSmartphone.Error, DBus.Error
+ public string get_resource_policy( string name ) throws FreeSmartphone.UsageError, FreeSmartphone.Error, DBus.Error
+ {
+ switch ( getResource( name ).policy )
+ {
+ case FreeSmartphone.UsageResourcePolicy.ENABLED:
+ return "enabled";
+ case FreeSmartphone.UsageResourcePolicy.DISABLED:
+ return "disabled";
+ case FreeSmartphone.UsageResourcePolicy.AUTO:
+ return "auto";
+ default:
+ var error = "unknown resource policy value %d for resource %s".printf( getResource( name ).policy, name );
+ logger.error( error );
+ throw new FreeSmartphone.Error.INTERNAL_ERROR( error );
+ }
+ }
+
+ //public void set_resource_policy( string name, FreeSmartphone.UsageResourcePolicy policy ) throws FreeSmartphone.UsageError, FreeSmartphone.Error, DBus.Error
+ public void set_resource_policy( string name, string policy ) throws FreeSmartphone.UsageError, FreeSmartphone.Error, DBus.Error
+ {
+ message( "set resource policy for %s to %s", name, policy );
+
+ if ( policy == "enabled" )
+ getResource( name ).setPolicy( FreeSmartphone.UsageResourcePolicy.ENABLED );
+ else if ( policy == "disabled" )
+ getResource( name ).setPolicy( FreeSmartphone.UsageResourcePolicy.DISABLED );
+ else if ( policy == "auto" )
+ getResource( name ).setPolicy( FreeSmartphone.UsageResourcePolicy.AUTO );
+ else
+ throw new FreeSmartphone.Error.INVALID_PARAMETER( "ResourcePolicy needs to be one of { \"enabled\", \"disabled\", \"auto\" }" );
+ }
+
+ public bool get_resource_state( string name ) throws FreeSmartphone.UsageError, DBus.Error
+ {
+ return getResource( name ).isEnabled();
+ }
+
+ public string[] get_resource_users( string name ) throws FreeSmartphone.UsageError, DBus.Error
+ {
+ return getResource( name ).allUsers();
+ }
+
+ public string[] list_resources() throws DBus.Error
+ {
+ string[] res = {};
+ foreach ( var key in resources.get_keys() )
+ res += key;
+ return res;
+ }
+
+ public void request_resource( DBus.BusName sender, string name ) throws FreeSmartphone.UsageError, DBus.Error
+ {
+ getResource( name ).addUser( sender );
+ }
+
+ public void release_resource( DBus.BusName sender, string name ) throws FreeSmartphone.UsageError, DBus.Error
+ {
+ getResource( name ).delUser( sender );
+ }
+
+ public void shutdown() throws DBus.Error
+ {
+ this.system_action( FreeSmartphone.UsageSystemAction.SHUTDOWN ); // DBUS SIGNAL
+ disableAllResources();
+ Posix.system( "shutdown -h now" );
+ }
+
+ public void reboot() throws DBus.Error
+ {
+ this.system_action( FreeSmartphone.UsageSystemAction.REBOOT ); // DBUS SIGNAL
+ disableAllResources();
+ Posix.system( "reboot" );
+ }
+
+ public void suspend() throws DBus.Error
+ {
+ this.system_action( FreeSmartphone.UsageSystemAction.SUSPEND ); // DBUS SIGNAL
+ // we need to suspend async, otherwise the dbus call would timeout
+ Idle.add( onIdleForSuspend );
+ }
+
+ // DBUS SIGNALS
+ public signal void resource_available( string name, bool availability );
+ public signal void resource_changed( string name, bool state, GLib.HashTable<string,GLib.Value?> attributes );
+ public signal void system_action( FreeSmartphone.UsageSystemAction action );
+}
+
+} /* end namespace */
+
+Usage.Controller instance;
+DBus.Connection dbusconn;
+
+public static string fso_factory_function( FsoFramework.Subsystem subsystem ) throws Error
+{
+ instance = new Usage.Controller( subsystem );
+ return "fsousage.controller";
+}
+
+public static void fso_shutdown_function()
+{
+#if PERSISTENCE
+ instance.savePersistentData();
+#endif
+}
+
+[ModuleInit]
+public static void fso_register_function( TypeModule module )
+{
+ debug( "usage controller fso_register_function()" );
+}
diff --git a/sys-mobilephone/fsousaged/files/lowlevel_kernel26-plugin.vala b/sys-mobilephone/fsousaged/files/lowlevel_kernel26-plugin.vala
new file mode 100644
index 0000000..9a1b877
--- /dev/null
+++ b/sys-mobilephone/fsousaged/files/lowlevel_kernel26-plugin.vala
@@ -0,0 +1,68 @@
+/**
+ * Copyright (C) 2009 Michael 'Mickey' Lauer <mlauer@vanille-media.de>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library 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
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+using GLib;
+
+using FsoUsage;
+
+class LowLevel.Kernel26 : FsoUsage.LowLevel, FsoFramework.AbstractObject
+{
+ construct
+ {
+ logger.info( "Registering kernel26 low level suspend/resume handling" );
+ // grab sysfs paths
+ var sysfs_root = config.stringValue( "cornucopia", "sysfs_root", "/sys" );
+ sys_power_state = Path.build_filename( sysfs_root, "power", "state" );
+ }
+
+ public override string repr()
+ {
+ return "<>";
+ }
+
+ public void suspend()
+ {
+ FsoFramework.FileHandling.write( "mem\n", sys_power_state );
+ }
+
+ public ResumeReason resume()
+ {
+ return ResumeReason.Unknown;
+ }
+}
+
+string sys_power_state;
+
+/**
+ * This function gets called on plugin initialization time.
+ * @return the name of your plugin here
+ * @note that it needs to be a name in the format <subsystem>.<plugin>
+ * else your module will be unloaded immediately.
+ **/
+public static string fso_factory_function( FsoFramework.Subsystem subsystem ) throws Error
+{
+ debug( "lowlevel_kernel26 fso_factory_function" );
+ return "fsousaged.lowlevel_kernel26";
+}
+
+[ModuleInit]
+public static void fso_register_function( TypeModule module )
+{
+ // do not remove this function
+}
diff --git a/sys-mobilephone/fsousaged/files/lowlevel_openmoko-plugin.vala b/sys-mobilephone/fsousaged/files/lowlevel_openmoko-plugin.vala
new file mode 100644
index 0000000..0ea906a
--- /dev/null
+++ b/sys-mobilephone/fsousaged/files/lowlevel_openmoko-plugin.vala
@@ -0,0 +1,130 @@
+/**
+ * Copyright (C) 2009 Michael 'Mickey' Lauer <mlauer@vanille-media.de>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library 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
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+using GLib;
+
+using FsoUsage;
+
+internal const string SYSFS_RESUME_REASON_PATH = "/class/i2c-adapter/i2c-0/0-0073/neo1973-resume.0/resume_reason";
+internal const string SYSFS_RESUME_SUBREASON_PATH = "/class/i2c-adapter/i2c-0/0-0073/resume_reason";
+
+class LowLevel.Openmoko : FsoUsage.LowLevel, FsoFramework.AbstractObject
+{
+ private HashTable<string,uint> intmap1;
+ private HashTable<string,uint> intmap2;
+
+ construct
+ {
+ logger.info( "Registering openmoko low level suspend/resume handling" );
+ // grab sysfs paths
+ var sysfs_root = config.stringValue( "cornucopia", "sysfs_root", "/sys" );
+ sys_power_state = Path.build_filename( sysfs_root, "power", "state" );
+ sys_resume_reason = Path.build_filename( sysfs_root, SYSFS_RESUME_REASON_PATH );
+ sys_resume_subreason = Path.build_filename( sysfs_root, SYSFS_RESUME_SUBREASON_PATH );
+
+ intmap1 = new HashTable<string,uint>( str_hash, str_equal );
+ intmap1.insert( "EINT00_ACCEL1", ResumeReason.Accelerometer );
+ intmap1.insert( "EINT01_GSM", ResumeReason.GSM );
+ intmap1.insert( "EINT02_BLUETOOTH", ResumeReason.Bluetooth );
+ intmap1.insert( "EINT03_DEBUGBRD", ResumeReason.Debug );
+ intmap1.insert( "EINT04_JACK", ResumeReason.Headphone );
+ intmap1.insert( "EINT05_WLAN", ResumeReason.WiFi );
+ intmap1.insert( "EINT06_AUXKEY", ResumeReason.AuxKey );
+ intmap1.insert( "EINT07_HOLDKEY", ResumeReason.Headphone );
+ intmap1.insert( "EINT08_ACCEL2", ResumeReason.Accelerometer );
+ intmap1.insert( "EINT09_PMU", ResumeReason.PMU );
+ intmap1.insert( "EINT10_NULL", ResumeReason.Invalid );
+ intmap1.insert( "EINT11_NULL", ResumeReason.Invalid );
+ intmap1.insert( "EINT12_GLAMO", ResumeReason.GFX );
+ intmap1.insert( "EINT13_NULL", ResumeReason.Invalid );
+ intmap1.insert( "EINT14_NULL", ResumeReason.Invalid );
+ intmap1.insert( "EINT15_NULL", ResumeReason.Invalid );
+
+ intmap2 = new HashTable<string,uint>( str_hash, str_equal );
+ intmap2.insert( "0000000200", ResumeReason.LowBattery );
+ intmap2.insert( "0002000000", ResumeReason.PowerKey );
+ }
+
+ public override string repr()
+ {
+ return "<>";
+ }
+
+ public void suspend()
+ {
+ FsoFramework.FileHandling.write( "mem\n", sys_power_state );
+ }
+
+ public ResumeReason resume()
+ {
+ var reasons = FsoFramework.FileHandling.read( sys_resume_reason ).split( "\n" );
+ var reasonkey = "unknown";
+ foreach ( var line in reasons )
+ {
+ if ( line.has_prefix( "*" ) )
+ {
+ reasonkey = line.substring( 2 );
+ break;
+ }
+ }
+ var reasonvalue = intmap1.lookup( reasonkey );
+ if ( reasonvalue == 0 )
+ {
+ logger.info( "No resume reason marked in %s".printf( sys_resume_reason ) );
+ return ResumeReason.Unknown;
+ }
+
+ if ( reasonvalue == ResumeReason.PMU )
+ {
+ logger.debug( "PMU resume reason marked in %s".printf( sys_resume_reason ) );
+
+ var subreasonkey = FsoFramework.FileHandling.read( sys_resume_subreason );
+ var subreasonvalue = intmap2.lookup( subreasonkey );
+ if ( subreasonvalue == 0 )
+ {
+ logger.debug( "Unknown subreason %s for PMU resume, please fix me!".printf( subreasonkey ) );
+ return ResumeReason.PMU;
+ }
+ return (ResumeReason)subreasonvalue;
+ }
+ return (ResumeReason)reasonvalue;
+ }
+}
+
+string sys_power_state;
+string sys_resume_reason;
+string sys_resume_subreason;
+
+/**
+ * This function gets called on plugin initialization time.
+ * @return the name of your plugin here
+ * @note that it needs to be a name in the format <subsystem>.<plugin>
+ * else your module will be unloaded immediately.
+ **/
+public static string fso_factory_function( FsoFramework.Subsystem subsystem ) throws Error
+{
+ debug( "lowlevel_openmoko fso_factory_function" );
+ return "fsousaged.lowlevel_openmoko";
+}
+
+[ModuleInit]
+public static void fso_register_function( TypeModule module )
+{
+ // do not remove this function
+}
diff --git a/sys-mobilephone/fsousaged/fsousaged-0.9.1.0.ebuild b/sys-mobilephone/fsousaged/fsousaged-0.9.1.0.ebuild
new file mode 100644
index 0000000..7635c0d
--- /dev/null
+++ b/sys-mobilephone/fsousaged/fsousaged-0.9.1.0.ebuild
@@ -0,0 +1,45 @@
+# Copyright 1999-2009 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: $
+
+inherit autotools
+
+DESCRIPTION="freesmartphone.org usage daemon"
+HOMEPAGE="http://www.freesmartphone.org"
+SRC_URI="http://www.freesmartphone.org/sources/${P}.tar.bz2"
+
+LICENSE="GPL-2"
+SLOT="0"
+KEYWORDS="~arm ~x86 ~amd64"
+IUSE=""
+
+RDEPEND=">=dev-libs/glib-2.18.0
+ >=dev-libs/libgee-0.3.0
+ >=media-libs/alsa-lib-1.0.20
+ >=sys-apps/dbus-1.2.1
+ >=dev-libs/dbus-glib-0.76
+ >=sys-mobilephone/libfso-glib-0.2.0
+ >=sys-mobilephone/libfsoframework-0.2.3"
+DEPEND="${RDEPEND}
+ >=dev-lang/vala-0.7.6"
+
+EAPI="2"
+
+src_prepare() {
+ cp "${FILESDIR}"/controller-plugin.vala "${S}"/src/plugins/controller/plugin.vala
+ cp "${FILESDIR}"/lowlevel_kernel26-plugin.vala "${S}"/src/plugins/lowlevel_kernel26/plugin.vala
+ cp "${FILESDIR}"/lowlevel_openmoko-plugin.vala "${S}"/src/plugins/lowlevel_openmoko/plugin.vala
+}
+
+src_install() {
+ emake DESTDIR="${D}" install || die "make install failed"
+}
+
+pkg_postinst() {
+ elog "To use fsousaged instead of ousaged edit the config in"
+ elog "/etc/frameworkd.conf , below the lines where [ousaged] appear make sure"
+ elog "that \"disable 1\" appear. And anywhere add the lines :"
+ elog " [fsousage]"
+ elog " [fsousage.controller]"
+ elog "With this the daemon will be used without any need of initscript."
+}