From f7ca11b202e442e759cca86a70d9c6d027e82e76 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Fri, 11 Oct 2013 08:38:51 -0500 Subject: if /dev/rfkill doesn't exist or isn't writable, then try to handle bluetooth toggles simply by toggling bluez Adapters' Powered property --- src/bluez.vala | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 106 insertions(+), 15 deletions(-) (limited to 'src/bluez.vala') diff --git a/src/bluez.vala b/src/bluez.vala index 8c8c1b6..82f34f4 100644 --- a/src/bluez.vala +++ b/src/bluez.vala @@ -22,12 +22,25 @@ /** * Bluetooth implementaion which uses org.bluez on DBus */ -public class Bluez: KillswitchBluetooth +public class Bluez: Bluetooth, Object { uint next_device_id = 1; org.bluez.Manager manager; org.bluez.Adapter default_adapter; + private bool _powered = false; + + private bool powered { + get { return _powered; } + set { _powered = value; update_enabled(); } + } + + private KillSwitch killswitch = null; + + private string adapter_path = null; + + private DBusConnection bus = null; + /* maps an org.bluez.Device's object_path to the org.bluez.Device proxy */ HashTable path_to_proxy; @@ -42,42 +55,85 @@ public class Bluez: KillswitchBluetooth public Bluez (KillSwitch killswitch) { - base (killswitch); + try + { + bus = Bus.get_sync (BusType.SYSTEM); + } + catch (Error e) + { + critical (@"$(e.message)"); + } - string adapter_path = null; + if (killswitch.is_valid()) + { + this.killswitch = killswitch; + killswitch.notify["blocked"].connect (() => update_enabled()); + update_enabled (); + } id_to_path = new HashTable (direct_hash, direct_equal); id_to_device = new HashTable (direct_hash, direct_equal); path_to_id = new HashTable (str_hash, str_equal); path_to_proxy = new HashTable (str_hash, str_equal); + reset_manager (); + } + + private void reset_manager () + { + string new_adapter_path = null; try { - manager = Bus.get_proxy_sync (BusType.SYSTEM, "org.bluez", "/"); + manager = bus.get_proxy_sync ("org.bluez", "/"); - // get the current default adapter & watch for future default adapters - adapter_path = manager.default_adapter (); + // if the default adapter changes, update our connections manager.default_adapter_changed.connect ((object_path) => on_default_adapter_changed (object_path)); + + // if the current adapter disappears, call clear_adapter() + manager.adapter_removed.connect ((object_path) => { + if (object_path == adapter_path) + clear_adapter (); + }); + + // get the current default adapter & watch for future default adapters + new_adapter_path = manager.default_adapter (); } catch (Error e) { critical (@"$(e.message)"); } - on_default_adapter_changed (adapter_path); + on_default_adapter_changed (new_adapter_path); } - private void on_default_adapter_changed (string? object_path) + private void clear_adapter () { - supported = object_path != null; + if (adapter_path != null) + debug (@"clearing adapter; was using $adapter_path"); + + path_to_proxy.remove_all (); + path_to_id.remove_all (); + id_to_path.remove_all (); + id_to_device.remove_all (); + + default_adapter = null; + adapter_path = null; + + discoverable = false; + powered = false; + } + + void on_default_adapter_changed (string? object_path) + { + clear_adapter (); if (object_path != null) try { - debug (@"using default adapter at $object_path"); + adapter_path = object_path; default_adapter = Bus.get_proxy_sync (BusType.SYSTEM, "org.bluez", - object_path); + adapter_path); default_adapter.property_changed.connect (() => on_default_adapter_properties_changed ()); @@ -104,6 +160,8 @@ public class Bluez: KillswitchBluetooth on_default_adapter_properties_changed (); } + /* When the default adapter's properties change, + update our own properties "powered" and "discoverable" */ private void on_default_adapter_properties_changed () { bool is_discoverable = false; @@ -217,7 +275,6 @@ public class Bluez: KillswitchBluetooth private void device_connect_on_interface (DBusProxy proxy, string interface_name) { - var bus = proxy.get_connection (); var object_path = proxy.get_object_path (); debug (@"trying to connect to $object_path: $(interface_name)"); @@ -359,11 +416,21 @@ public class Bluez: KillswitchBluetooth devices_changed (); } + /* update the 'enabled' property by looking at the killswitch state + and the 'powered' property state */ + void update_enabled () + { + var blocked = (killswitch != null) && killswitch.blocked; + debug (@"in upate_enabled, powered is $powered, blocked is $blocked"); + enabled = powered && !blocked; + } + + //// //// Public API //// - public override void set_device_connected (uint id, bool connected) + public void set_device_connected (uint id, bool connected) { var device = id_to_device.lookup (id); var path = id_to_path.lookup (id); @@ -380,7 +447,7 @@ public class Bluez: KillswitchBluetooth } } - public override void try_set_discoverable (bool b) + public void try_set_discoverable (bool b) { if (discoverable != b) try { @@ -392,8 +459,32 @@ public class Bluez: KillswitchBluetooth } } - public override List get_devices () + public List get_devices () { return id_to_device.get_values(); } + + public bool supported { get; protected set; default = false; } + public bool discoverable { get; protected set; default = false; } + public bool enabled { get; protected set; default = false; } + + public void try_set_enabled (bool b) + { + if (killswitch != null) + { + debug (@"setting killswitch blocked to $(!b)"); + killswitch.try_set_blocked (!b); + } + + if (default_adapter != null) try + { + debug (@"setting bluez Adapter's Powered property to $b"); + default_adapter.set_property ("Powered", new Variant.boolean (b)); + powered = b; + } + catch (Error e) + { + critical (@"$(e.message)"); + } + } } -- cgit v1.2.3